import os
import time
import subprocess
import multiprocessing
import threading
import signal


# SIM卡状态
g_sim_sta = False
#检卡次数
# g_check_sim_count = 0
# 驻网状态
g_net_sta = False
# 退出标志
g_exit = False
# 程序退出标志
g_program_exit = False
# 全局变量存储进程和线程
g_process = None
g_read_thread = None
g_process_thread = None
g_parent_conn = None
g_child_conn = None

def read_data(conn, process):
    try:
        while not g_exit:
            data = process.stdout.readline()
            if not data and process.poll() is not None:
                break
            if data:
                conn.send(data)
    except Exception as e:
        if not g_exit:
            print(f"Error in read_data: {e}")
    finally:
        if not g_exit:
            print("Pipe closed, exiting read thread.")
        conn.close()

def process_data(conn):
    global g_sim_sta, g_net_sta, g_exit
    try:
        while not g_exit:
            data = conn.recv()
            if not data:
                break
            data_str = data.decode('utf-8')
            if '+CPIN: READY' in data_str:
                print('SIM card detected.')
                g_sim_sta = True
            if '+COPS:' in data_str:
                fields = data_str.split(',')
                if len(fields) >= 3:
                    print('network register success.')
                    g_net_sta = True
            if '+CGSN:' in data_str:
                s = data_str.split(':')
                print('IMEI号:', s[1].strip())
            if '+MCCID:' in data_str:
                s = data_str.split(':')
                print('ICCID号:', s[1].strip())
            if '+CSQ:' in data_str:
                s = data_str.split(":")[1].split(",")[0].strip()
                print('信号值：', s)

    except EOFError:
        if not g_exit:
            print("Pipe closed, exiting processing thread.")
    except Exception as e:
        if not g_exit:
            print(f"Error in process_data: {e}")

# 挂载
def cat1_mount():
    print("Mounting CAT1 device...")
    #pwr
    if os.path.exists("/sys/class/gpio/gpio128"):
        os.system('echo 128 > /sys/class/gpio/unexport')
    os.system('echo 128 > /sys/class/gpio/export')
    os.system('echo \"out\" > /sys/class/gpio/gpio128/direction')
    os.system('echo 1 > /sys/class/gpio/gpio128/value')

    #rst
    if os.path.exists("/sys/class/gpio/gpio130"):
        os.system('echo 130 > /sys/class/gpio/unexport')
    os.system('echo 130 > /sys/class/gpio/export')
    os.system('echo \"out\" > /sys/class/gpio/gpio130/direction')
    result = os.system('echo 0 > /sys/class/gpio/gpio130/value')
    if result != 0:
        raise RuntimeError("Failed to mount CAT1 device.")
    time.sleep(10)

# 取消挂载
def cat1_umount():
    print("Unmounting CAT1 device...")
    os.system('ifconfig eth0 down')
    os.system('kill -9 $(ps | grep "cat /dev/ttyUSB2" | grep -v grep | awk \'{print $1}\')')
    #rst
    os.system('echo 1 > /sys/class/gpio/gpio130/value')
    time.sleep(0.3)
    #pwr
    os.system('echo 0 > /sys/class/gpio/gpio128/value')
    time.sleep(0.3)

def cat1_remount():
    """
    重新挂载CAT1设备
    """
    print("Remounting CAT1 device...")
    cat1_umount()
    time.sleep(2)  # 等待一段时间确保设备完全卸载
    cat1_mount()
    print("Remount completed successfully!")

# 拨号
def cat1_dialing():
    global g_program_exit
    print("Starting dialing...")
    os.system('echo -e \'ATE0\r\n\' > /dev/ttyUSB2')   

    last_print_time = time.time()
    # while True:
    while not g_program_exit:
        os.system('echo -e \'AT+CPIN?\r\n\' > /dev/ttyUSB2')
        if g_sim_sta == False:
            print('No SIM card detected....')
            current_time = time.time()
            if current_time - last_print_time >= 15:
                last_print_time = current_time
                cat1_remount()
            time.sleep(1)
        else:
            break

    for i in range(20):
        os.system('echo -e \'AT+COPS?\r\n\' > /dev/ttyUSB2')
        if g_net_sta == False:
            time.sleep(1)
            if i == 19:
                print('network register fail...')
                return False
        else:
            break

    os.system('echo -e \'AT+CGDCONT?\r\n\' > /dev/ttyUSB2')  
    os.system('echo -e \'AT+MDIALUP?\r\n\' > /dev/ttyUSB2')

    os.system('echo -e \'AT+MDIALUP=1,1\r\n\' > /dev/ttyUSB2')
    os.system('ifconfig eth0 up')
    os.system('udhcpc -i eth0')
    time.sleep(3)
    print("Dialing completed successfully!")
    return True

# 检查网络连接状态
def check_network():
    """
    通过ping公共DNS服务器检查网络连接
    返回True表示网络正常,False表示网络断开
    """
    try:
        # 尝试ping多个服务器，增加可靠性
        servers = ['8.8.8.8', '114.114.114.114', '223.5.5.5']
        for server in servers:
            result = subprocess.run(
                ['ping', '-c', '3', '-W', '2', server],
                stdout=subprocess.DEVNULL,
                stderr=subprocess.DEVNULL
            )
            if result.returncode == 0:
                return True
        return False
    except Exception as e:
        print(f"Error checking network: {e}")
        return False

# 连接CAT1设备
def connect_cat1():
    global g_sim_sta, g_net_sta, g_exit
    global g_process, g_read_thread, g_process_thread, g_parent_conn, g_child_conn
    
    # 重置状态
    g_sim_sta = False
    g_net_sta = False
    g_exit = False
    
    try:
        # 挂载设备
        cat1_mount()
        
        # 启动子进程读取串口数据
        g_process = subprocess.Popen(['cat', '/dev/ttyUSB2'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        
        # 创建管道
        g_parent_conn, g_child_conn = multiprocessing.Pipe(duplex=False)
        
        # 启动线程
        g_read_thread = threading.Thread(target=read_data, args=(g_child_conn, g_process))
        g_process_thread = threading.Thread(target=process_data, args=(g_parent_conn,))
        
        g_read_thread.start()
        g_process_thread.start()
        
        # 执行拨号
        if not cat1_dialing():
            print("Dialing failed!")
            return False
        
        # 获取设备信息
        os.system('echo -e \'AT+CGSN=1\r\n\' > /dev/ttyUSB2')  # 获取IMEI号
        time.sleep(1)
        os.system('echo -e \'AT+CSQ\r\n\' > /dev/ttyUSB2')     # 获取信号值
        time.sleep(1)
        os.system('echo -e \'AT+MCCID\r\n\' > /dev/ttyUSB2')   # 获取ICCID
        time.sleep(1)
        
        return True
        
    except Exception as e:
        print(f"Error connecting CAT1: {e}")
        return False

# 断开CAT1连接
def disconnect_cat1():
    global g_exit, g_process, g_read_thread, g_process_thread
    
    print("Disconnecting CAT1...")
    
    # 设置退出标志
    g_exit = True
    
    # 终止子进程
    if g_process and g_process.poll() is None:
        g_process.terminate()
        try:
            g_process.wait(timeout=5)
        except subprocess.TimeoutExpired:
            g_process.kill()
            g_process.wait()
    
    # 等待线程结束
    if g_read_thread and g_read_thread.is_alive():
        g_read_thread.join(timeout=5)
    if g_process_thread and g_process_thread.is_alive():
        g_process_thread.join(timeout=5)
    
    # 卸载设备
    cat1_umount()
    
    # 等待一段时间确保清理完成
    time.sleep(2)

# 信号处理函数
def signal_handler(sig, frame):
    global g_program_exit
    print("\nReceived interrupt signal, shutting down...")
    g_program_exit = True

def main_test():
    global g_program_exit
    
    # 注册信号处理器 
    signal.signal(signal.SIGINT, signal_handler)     # SIGINT : 中断信号，通常由用户按下Ctrl+C触发
    signal.signal(signal.SIGTERM, signal_handler)    # SIGTERM : 终止信号，通常由系统或其他进程发送，要求程序正常退出
    
    # 网络检查失败计数器
    network_fail_count = 0
    max_fail_count = 3
    check_interval = 30  # 每30秒检查一次网络
    
    print("Starting CAT1 network monitor...")
    
    # 初始连接
    if not connect_cat1():
        print("Initial connection failed!")
        return
    
    print(f"Initial connection successful! Starting network monitoring (check every {check_interval}s)...")
    
    # 主循环：监控网络状态
    while not g_program_exit:
        try:
            # 等待检查间隔
            for _ in range(check_interval):
                if g_program_exit:
                    break
                time.sleep(1)
            
            if g_program_exit:
                break
            
            # 检查网络状态
            if check_network():
                if network_fail_count > 0:
                    print(f"Network recovered! (was down for {network_fail_count} checks)")
                network_fail_count = 0
            else:
                network_fail_count += 1
                print(f"Network check failed ({network_fail_count}/{max_fail_count})")
                
                # 如果连续失败达到阈值，则重新连接
                if network_fail_count >= max_fail_count:
                    print("Network disconnected! Attempting to reconnect...")
                    
                    # 断开当前连接
                    disconnect_cat1()
                    # 重试连接
                    retry_count = 0
                    max_retries = 3
                    while retry_count < max_retries and not g_program_exit:
                        retry_count += 1
                        print(f"Reconnection attempt {retry_count}/{max_retries}...")
                        
                        if connect_cat1():
                            print("Reconnection successful!")
                            network_fail_count = 0
                            break
                        else:
                            print(f"Reconnection failed, waiting 10 seconds before retry...")
                            for _ in range(10):
                                if g_program_exit:
                                    break
                                time.sleep(1)
                    
                    if retry_count >= max_retries:
                        print("Failed to reconnect after maximum retries!")
                        # 可以选择继续尝试或退出程序
                        g_program_exit = True
        
        except Exception as e:
            print(f"Error in main loop: {e}")
            time.sleep(5)
    
    # 清理并退出
    print("Shutting down...")
    disconnect_cat1()
    print("Program terminated.")

# if __name__ == "__main__":
#     main()